package com.ponhu.ea2.goodsCenter.provider.service.impl;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ponhu.ea2.common.basic.model.PagedResult;
import com.ponhu.ea2.constants.CommonConstant;
import com.ponhu.ea2.constants.DictConstant;
import com.ponhu.ea2.dto.PhInventoryAppraisalDto;
import com.ponhu.ea2.dto.PhInventoryDetailEditDto;
import com.ponhu.ea2.dto.PhInventoryGoodsEditDto;
import com.ponhu.ea2.entity.*;
import com.ponhu.ea2.enums.InventoryAppraisalEnum;
import com.ponhu.ea2.enums.ResponseCodeEnum;
import com.ponhu.ea2.goodsCenter.provider.mapper.InventoryMapper;
import com.ponhu.ea2.goodsCenter.provider.mapper.MaterialMapper;
import com.ponhu.ea2.goodsCenter.provider.mapper.PhCategoryMapper;
import com.ponhu.ea2.goodsCenter.provider.mapper.PhInventoryDetailMapper;
import com.ponhu.ea2.goodsCenter.provider.service.*;
import com.ponhu.ea2.goodsCenter.provider.utils.DataConverterUtils;
import com.ponhu.ea2.goodsCenter.provider.utils.LocalDateUtil;
import com.ponhu.ea2.goodsCenter.provider.utils.ProBeanUtils;
import com.ponhu.ea2.goodsCenter.provider.utils.ProObjectUtil;
import com.ponhu.ea2.query.InventoryInfoQuery;
import com.ponhu.ea2.query.PickInventoryQuery;
import com.ponhu.ea2.scmcenter.model.dto.procurementoder.UpdateProductDto;
import com.ponhu.ea2.stockcenter.service.bms.StockCommonService;
import com.ponhu.ea2.stockcenter.vo.StockMqVO;
import com.ponhu.ea2.support.exception.BusinessRuntimeException;
import com.ponhu.ea2.vo.*;
import io.netty.util.concurrent.FastThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

import static com.ponhu.ea2.enums.ResponseCodeEnum.INVENTORY_CCIC_EXCEPTION_800205;
import static com.ponhu.ea2.enums.ResponseCodeEnum.INVENTORY_EDIT_EXCEPTION_800204;

@Slf4j
@Service
public class InventoryServiceImpl
        extends ServiceImpl<InventoryMapper, Inventory>
        implements InventoryService {

    @Autowired
    private FastThreadLocal<List<Material>> materialsLocal;
    @Autowired
    private FastThreadLocal<Boolean> subQueryEmptyLocal;
    @Autowired
    private FastThreadLocal<List<PhCategoryLevel3Vo>> categorysLocal;

    @Autowired
    private MaterialMapper materialMapper;
    @Autowired
    private InventoryMapper inventoryMapper;
    @Resource
    private PhCategoryMapper phCategoryMapper;
    @Autowired
    private PhInventoryDetailMapper phInventoryDetailMapper;

    @Autowired
    private MaterialService materialService;

    @Autowired
    private OperationRecordLogsService operationRecordLogsService;

    @Resource
    PhInventoryAccessoryService phInventoryAccessoryService;

    @Resource
    PhInventoryPropertyValueMdService phInventoryPropertyValueMdService;

    @Resource
    InventoryService inventoryService;

    @Resource
    PhMaterialPropertyValueMdService phMaterialPropertyValueMdService;

    @DubboReference(version = "1.0.0", check = false)
    private StockCommonService stockCommonService;

    @Override
    public List<Inventory> getInventoryListByCodes(List<String> inventoryCodes) {

        if (CollectionUtils.isEmpty(inventoryCodes)) return Lists.newArrayList();

        LambdaQueryWrapper<Inventory> queryWrapper = Wrappers
                .lambdaQuery(Inventory.class)
                .in(Inventory::getInventoryCode, inventoryCodes);

        return list(queryWrapper);
    }

    @Override
    public Inventory getInventoryByCode(String inventoryCode) {
        LambdaQueryWrapper<Inventory> queryWrapper = Wrappers
                .lambdaQuery(Inventory.class)
                .eq(Inventory::getInventoryCode, inventoryCode)
                .last("LIMIT 1");

        return getOne(queryWrapper);
    }

    /**
     * 条件查询全部货品列表
     *
     * @return
     */
    @Override
    public IPage<Inventory> getAllInventorys(InventoryInfoQuery inventoryInfoQuery) {

        // 构建查询条件
        LambdaQueryWrapper<Inventory> queryWrapper =
                dealWithWrapper(Wrappers.lambdaQuery(Inventory.class), inventoryInfoQuery);
        if (BooleanUtils.isTrue(subQueryEmptyLocal.get())) return new Page<>();

        // 构建分页信息
        Page queryPageInfo = new Page(inventoryInfoQuery.getPageIndex(), inventoryInfoQuery.getPageSize());

        return page(queryPageInfo, queryWrapper);
    }

    /**
     * 根据货品编码修改货品相关信息
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void syncInventoryAppraisal(PhInventoryAppraisalDto phInventoryAppraisalDto) {

        Integer isDoneCcic = phInventoryAppraisalDto.getIsDoneCcic();
        if (isDoneCcic == InventoryAppraisalEnum.isDoneCcic_1.getCode())
            isDoneCcic = InventoryAppraisalEnum.isDoneCcic_4.getCode();
        LambdaUpdateWrapper<Inventory> updateWrapper = Wrappers.lambdaUpdate(Inventory.class)
                .eq(Inventory::getInventoryCode, phInventoryAppraisalDto.getInventoryCode())
                .set(Inventory::getIsDoneCcic, isDoneCcic);

        if (!update(updateWrapper))
            throw new BusinessRuntimeException(INVENTORY_CCIC_EXCEPTION_800205);
    }

    /**
     * 编辑货品基本信息
     *
     * @param inventory
     * @param detailEditDto
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void editPhInventory(Inventory inventory, PhInventoryDetailEditDto detailEditDto) {
        inventory = ProBeanUtils.copyProperties(detailEditDto, Inventory.class)
                .setId(detailEditDto.getInventoryId());
        // 处理一下主图
        inventory.setMainImage(detailEditDto.getDetailImage().split("\\|")[0]);
        if (StringUtils.isBlank(inventory.getRemarks())) {
            inventory.setRemarks("");
        }
        if(StringUtils.isBlank(inventory.getItemId())){
            inventory.setItemId("");
            inventory.setBxjAiJson("");
        }
        if (!updateById(inventory))
            throw new BusinessRuntimeException(INVENTORY_EDIT_EXCEPTION_800204);
    }

    /**
     * 根据货品ID修改货品入库价
     *
     * @param editDto
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void editInventoryWarehousePrice(PhInventoryGoodsEditDto editDto) {

        Inventory inventory = new Inventory()
                .setId(editDto.getInventoryId())
                .setWarehousePrice(editDto.getWarehousePrice());

        if (!updateById(inventory)) {
            throw new BusinessRuntimeException(ResponseCodeEnum
                    .INVENTORY_EDIT_EXCEPTION_800208);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void checkAndSaveFirstEdit(PhInventoryGoodsEditDto editDto) {
        // 根据货品编码查询是否已经存在
        PhInventoryDetail phInventoryDetail = phInventoryDetailMapper
                .selectOne(new LambdaQueryWrapper<PhInventoryDetail>()
                        .eq(PhInventoryDetail::getInventoryId, editDto.getInventoryId()));
        if (ObjectUtils.isEmpty(phInventoryDetail)) {
            // 根据货品id获取货品信息
            Inventory inventory = inventoryMapper.selectById(editDto.getInventoryId());
            phInventoryDetail = new PhInventoryDetail()
                    .setInventoryId(editDto.getInventoryId())
                    .setInventoryCode(inventory.getInventoryCode())
                    .setFirstEditId(editDto.getOperatorId())
                    .setFirstEditName(editDto.getOperatorName())
                    .setFirstEditTime(LocalDateUtil.dateToLocalDateTime(new Date()));
            if (phInventoryDetailMapper.insert(phInventoryDetail) != 1) {
                throw new BusinessRuntimeException(ResponseCodeEnum
                        .INVENTORY_EDIT_EXCEPTION_800208);
            }
        }
    }

    @Override
    public UpdateProductDto getPhInventoryByIdForPurchase(Long inventoryId) {
        return inventoryMapper.getPhInventoryByIdForPurchase(inventoryId);
    }

    /**
     * 选品列表汇总结果查询
     * @param query
     * @return
     */
    @Override
    public PickInventoryStatisticsVo getPickInventoryStatisticsInfo(PickInventoryQuery query) {
        if (CollectionUtils.isNotEmpty(query.getWarehouseWayList()) ||
                (query.getPurchaseTypeId() != null && query.getPurchaseTypeId() > 0) ||
                (query.getPurchaseChannelId() != null && query.getPurchaseChannelId() > 0) ||
                StringUtils.isNotBlank(query.getVendorName())) {
            return inventoryMapper.getPickInventoryStatisticsForPurchase(query);

        }else if (query.getIsSales() != null ||
                query.getSalesStockNumMin() != null || query.getSalesStockNumMax() != null) {
            return inventoryMapper.getPickInventoryStatisticsForStockSales(query);

        } else {
            return inventoryMapper.getPickInventoryStatisticsByCondition(query);
        }

    }

    @Override
    public List<PhGoodsStatusToAmqpVo> getGoodsStatusByCode(List<String> inventoryCodes) {
        return inventoryMapper.getGoodsStatusByCode(inventoryCodes);
    }

    @Override
    public List<PhGoodsPriceToAmqpVo> getGoodsPriceByCode(List<String> inventoryCodes) {

        return inventoryMapper.getGoodsPriceByCode(inventoryCodes);
    }

    @Override
    public List<PhInventoryToAmqpVo> getInventoryBasicByCode(List<String> inventoryCodes) {
        // 查询所有库存信息
        /*Map<String, Integer> stockMap = stockCommonService.getSaleStockMqVoList(inventoryCodes)
                .stream().collect(Collectors.toMap(StockMqVO::getInventoryCode, StockMqVO::getStock));
*/
        return inventoryMapper.getInventoryBasicByCode(inventoryCodes).stream().map(item -> {
            // 根据货品编码获取附件配件
            List<PhInventoryAccessory> list = phInventoryAccessoryService.list(
                    new LambdaQueryWrapper<PhInventoryAccessory>()
                            .eq(PhInventoryAccessory::getInventoryCode, item.getInventoryCode()));
            item.setAnnex(list.stream().filter(py -> py.getDictType().equals(DictConstant.INVENTORY_ANNEX))
                    .map(PhInventoryAccessory::getDictItemLabel).collect(Collectors.joining(",")));
            item.setAccessory(list.stream().filter(py -> py.getDictType().equals(DictConstant.INVENTORY_ACCESSORY))
                    .map(PhInventoryAccessory::getDictItemLabel).collect(Collectors.joining(",")));
            item.setPropertyMap(propertyMap(item.getInventoryCode()));
            //item.setStockNum(stockMap.get(item.getInventoryCode()));
            return item;
        }).collect(Collectors.toList());
    }

    public Map<String,String> propertyMap(String inventoryCode){
        Inventory inventory = inventoryService.getInventoryByCode(inventoryCode);
        List<PhPropertyVo> propertyList = Lists.newArrayList();
        List<PhPropertyVo> ivtPropVos = phInventoryPropertyValueMdService.getPropertyValueList(inventory.getId());
        propertyList.addAll(ivtPropVos);

        if (ObjectUtils.isNotEmpty(inventory.getMaterialId())) {
            List<PhPropertyVo> materialPropVos = phMaterialPropertyValueMdService
                    .getPropertyValueMap(inventory.getMaterialId());
            propertyList.addAll(materialPropVos);
        }
        return propertyList.stream()
                .collect(Collectors.toMap(PhPropertyVo::getPropertyName, PhPropertyVo::getPropertyValue));
    }

    /**
     * 根据条件分页查询选品列表数据
     *
     * @param pickInventoryQuery
     * @return
     */
    @Override
    public PagedResult<PickInventoryVo> getPickInventoryListByCondition(PickInventoryQuery pickInventoryQuery) {
        Page<PickInventoryVo> objectPage = new Page<>();
        objectPage.setCurrent(pickInventoryQuery.getPageIndex());
        objectPage.setSize(pickInventoryQuery.getPageSize());

        IPage<PickInventoryVo> result;
        if (CollectionUtils.isNotEmpty(pickInventoryQuery.getWarehouseWayList()) ||
                (pickInventoryQuery.getPurchaseTypeId() != null && pickInventoryQuery.getPurchaseTypeId() > 0) ||
                (pickInventoryQuery.getPurchaseChannelId() != null && pickInventoryQuery.getPurchaseChannelId() > 0) ||
                StringUtils.isNotBlank(pickInventoryQuery.getVendorName())) {
            objectPage.setCountId("getPickInventoryPageListForPurchase_count");
        }

        if (pickInventoryQuery.getIsSales() != null ||
                pickInventoryQuery.getSalesStockNumMin() != null || pickInventoryQuery.getSalesStockNumMax() != null) {
            if(objectPage.getCountId() == null){
                objectPage.setCountId("getPickInventoryPageListForStockSales_count");
            }
            result = inventoryMapper.getPickInventoryPageListForStockSales(pickInventoryQuery, objectPage);

        } else {
            if(objectPage.getCountId() == null){
                objectPage.setCountId("getPickInventoryPageListByCondition_count");
            }
            result = inventoryMapper.getPickInventoryPageListByCondition(pickInventoryQuery, objectPage);
        }

        return DataConverterUtils.convertToPagedResult(result, result.getRecords());
    }

    /**
     * 获取选品导出数据列表
     *
     * @param query
     * @return
     */
    @Override
    public List<PickInventoryDetailVo> getImportPickInventoryDataList(PickInventoryQuery query) {
        if (query.getIsSales() != null ||
                query.getSalesStockNumMin() != null || query.getSalesStockNumMax() != null) {
            return inventoryMapper.getPickInventoryListForStockSales(query);

        } else {
            return inventoryMapper.getPickInventoryListByCondition(query);
        }
    }

    /**
     * 构建查询条件
     *
     * @param queryWrapper
     * @param inventoryInfoQuery
     * @return
     */
    public LambdaQueryWrapper<Inventory> dealWithWrapper(LambdaQueryWrapper<Inventory> queryWrapper,
                                                         InventoryInfoQuery inventoryInfoQuery) {

        // 异步编排：根据物料编码查询物料ID
        AtomicBoolean subQueryEmpty = new AtomicBoolean(false);
        CompletableFuture<List<Material>> materialFuture = CompletableFuture.supplyAsync(() -> {
            List<Material> materials = Lists.newArrayList();
            if (ProObjectUtil.isNotEmpty(inventoryInfoQuery.getSeriesId()) || StringUtils.isNotBlank(inventoryInfoQuery.getSeriesName()) ||
                    ProObjectUtil.isNotEmpty(inventoryInfoQuery.getModelId()) || StringUtils.isNotBlank(inventoryInfoQuery.getModelName())) {
                materials = materialMapper.getMaterialBySeriesOrModel(inventoryInfoQuery.getSeriesId(),
                        inventoryInfoQuery.getSeriesName(), inventoryInfoQuery.getModelId(), inventoryInfoQuery.getModelName());
                if (CollectionUtils.isEmpty(materials)) subQueryEmpty.set(true);
            }
            if (StringUtils.isNotBlank(inventoryInfoQuery.getMaterialCode())) {
                materials = materialService.getMaterialByCode(inventoryInfoQuery.getMaterialCode().trim());
                if (CollectionUtils.isEmpty(materials)) subQueryEmpty.set(true);
            }
            return materials;
        });

        // 异步编排：根据一、二、三级类目ID获取所有三级类目集合
        CompletableFuture<List<PhCategoryLevel3Vo>> categorysFuture = CompletableFuture.supplyAsync(() -> {
            Long level1CategoryId = inventoryInfoQuery.getLevel1CategoryId();
            Long level2CategoryId = inventoryInfoQuery.getLevel2CategoryId();
            Long level3CategoryId = inventoryInfoQuery.getLevel3CategoryId();
            List<PhCategoryLevel3Vo> categoryLevel3Vos = Lists.newArrayList();
            if (ProObjectUtil.isNotEmpty(level1CategoryId) || ProObjectUtil.isNotEmpty(level2CategoryId)
                    || ProObjectUtil.isNotEmpty(level3CategoryId)) {
                categoryLevel3Vos = phCategoryMapper.getCategoryLevel3VosById(level1CategoryId, level2CategoryId, level3CategoryId);
                if (CollectionUtils.isEmpty(categoryLevel3Vos)) subQueryEmpty.set(true);
            }
            return categoryLevel3Vos;
        });

        // 根据货品是否中检
        if (ProObjectUtil.isNotEmpty(inventoryInfoQuery.getIsDoneCcic())) {
            queryWrapper.eq(Inventory::getIsDoneCcic, inventoryInfoQuery.getIsDoneCcic());
        }
        // 根据货品类型查询
        if (ProObjectUtil.isNotEmpty(inventoryInfoQuery.getInventoryType())) {
            queryWrapper.eq(Inventory::getInventoryType, inventoryInfoQuery.getInventoryType());
        }
        // 根据是否是二奢查询
        if (ProObjectUtil.isNotEmpty(inventoryInfoQuery.getIsSecondhand())) {
            queryWrapper.eq(Inventory::getIsSecondhand, inventoryInfoQuery.getIsSecondhand());
        }
        // 根据来源渠道(货品渠道)查询
        if (ProObjectUtil.isNotEmpty(inventoryInfoQuery.getInventoryChannel())) {
            queryWrapper.eq(Inventory::getInventoryChannel, inventoryInfoQuery.getInventoryChannel());
        }
        // 根据成色查询
        if (ProObjectUtil.isNotEmpty(inventoryInfoQuery.getQuality())) {
            queryWrapper.eq(Inventory::getQuality, inventoryInfoQuery.getQuality());
        }
        // 根据货品编码查询
        if (StringUtils.isNotBlank(inventoryInfoQuery.getInventoryCode())) {
            queryWrapper.eq(Inventory::getInventoryCode, inventoryInfoQuery.getInventoryCode().trim());
        }
        // 根据货品名称模糊查询
        if (StringUtils.isNotBlank(inventoryInfoQuery.getInventoryName())) {
            queryWrapper.like(Inventory::getInventoryName, inventoryInfoQuery.getInventoryName().trim());
        }
        // 根据品牌ID查询
        if (ProObjectUtil.isNotEmpty(inventoryInfoQuery.getBrandId())) {
            queryWrapper.eq(Inventory::getBrandId, inventoryInfoQuery.getBrandId());
        }
        // 根据是否是云商
        if (ProObjectUtil.isNotEmpty(inventoryInfoQuery.getIsCloud())) {
            if (inventoryInfoQuery.getIsCloud() == DictConstant.INVENTORY_SOURC_CLOUD) {
                queryWrapper.eq(Inventory::getInventoryChannel, DictConstant.INVENTORY_SOURC_CLOUD);
            } else {
                queryWrapper.ne(Inventory::getInventoryChannel, DictConstant.INVENTORY_SOURC_CLOUD);
            }
        }
        // 根据货品创建时间
        LocalDateTime startTime = inventoryInfoQuery.getStartTime();
        LocalDateTime endTime = inventoryInfoQuery.getEndTime();
        if (ObjectUtils.isNotEmpty(startTime) && ObjectUtils.isNotEmpty(endTime)) {
            queryWrapper.between(Inventory::getCreatedTime, startTime, endTime);
        }

        List<Material> materialList = Lists.newArrayList();
        List<PhCategoryLevel3Vo> categoryList = Lists.newArrayList();
        materialFuture.thenAcceptBoth(categorysFuture, (materials, categorys) -> {
            if (ObjectUtils.isNotEmpty(materials)) {
                materialList.addAll(materials);
                queryWrapper.in(Inventory::getMaterialId,
                        materials.stream().map(Material::getId).collect(Collectors.toList()));
            }
            if (CollectionUtils.isNotEmpty(categorys)) {
                categoryList.addAll(categorys);
                List<Long> categoryIds = categorys.stream()
                        .map(PhCategoryLevel3Vo::getLevel3Id).collect(Collectors.toList());
                queryWrapper.in(Inventory::getCategoryId, categoryIds);
            }
        }).join();
        materialsLocal.set(materialList);
        categorysLocal.set(categoryList);
        subQueryEmptyLocal.set(subQueryEmpty.get());

        // 增加编辑人和编辑时间的查询条件
        LambdaQueryWrapper<OperationRecordLogs> wrapper = new LambdaQueryWrapper<>();
        if (CollectionUtils.isNotEmpty(inventoryInfoQuery.getEditIds())) {
            wrapper.in(OperationRecordLogs::getOperatorId, inventoryInfoQuery.getEditIds())
                    .eq(OperationRecordLogs::getBusinessTable, CommonConstant.BUSINESS_TYPE_INVENTORY);
        }
        if (ObjectUtils.isNotEmpty(inventoryInfoQuery.getEditStartTime())
                && ObjectUtils.isNotEmpty(inventoryInfoQuery.getEditEndTime())) {
            wrapper.between(
                    OperationRecordLogs::getCreateTime,
                    inventoryInfoQuery.getEditStartTime(),
                    inventoryInfoQuery.getEditEndTime());
        }
        if (CollectionUtils.isNotEmpty(inventoryInfoQuery.getEditIds()) ||
                ObjectUtils.isNotEmpty(inventoryInfoQuery.getEditStartTime())) {
            List<Long> collect = operationRecordLogsService.list(wrapper).stream()
                    .map(OperationRecordLogs::getRecordId).collect(Collectors.toList());
            queryWrapper.in(Inventory::getId, CollectionUtils.isNotEmpty(collect) ? collect : Arrays.asList(0));
        }
        if (StringUtils.isNotBlank(inventoryInfoQuery.getRemarks())) {
            queryWrapper.like(Inventory::getRemarks, inventoryInfoQuery.getRemarks());
        }
        if(StringUtils.isNotBlank(inventoryInfoQuery.getMaintainResult())){
            queryWrapper.eq(Inventory::getMaintainResult,inventoryInfoQuery.getMaintainResult());
        }
        return queryWrapper.orderByDesc(Inventory::getCreatedTime);
    }

}